package com.smedi.ismedi.authoritymanagement.core.port.adapter.persistence.repository.impl;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.smedi.ismedi.authority.starter.util.AuthorityUtil;
import com.smedi.ismedi.authority.starter.util.JsonHelper;
import com.smedi.ismedi.authoritymanagement.core.domain.aggregatemodel.AuthorityAccess;
import com.smedi.ismedi.authoritymanagement.core.domain.aggregatemodel.AuthorityInfo;
import com.smedi.ismedi.authoritymanagement.core.domain.repository.UserTokenRepository;
import com.smedi.ismedi.authoritymanagement.core.infrastructure.constant.CustomError;
import com.smedi.ismedi.cache.starter.util.RedisUtil;
import com.smedi.ismedi.web.starter.exception.LogicException;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;

import static com.smedi.ismedi.authority.starter.constant.AuthorityConstant.ISMEDI_ACCESS_TOKEN;
import static com.smedi.ismedi.authoritymanagement.core.infrastructure.constant.ConstantField.TOKEN_TIME;

/**
 * @Author: xulinjun
 * @Date: 2021-7-13 9:26
 */
@Slf4j
@Repository
@AllArgsConstructor
public class UserTokenRepositoryImpl implements UserTokenRepository {
    private final Environment env;

    private final RedisUtil redisUtil;

    private final String[] multiTerminalLoginEnvs = new String[]{"local", "dev", "crp", "test"}; // 允许多端登录的环境
    private final AuthorityUtil authorityUtil;
    private final ObjectMapper objectMapper;
    private final JsonHelper jsonHelper;


    @Override
    public void saveTokenAccessAndExpress(String path, AuthorityAccess authorityAccess, Long express) {
        // 用户key路径，一个用户key下对应登录token
        String userKeyPath = path + authorityAccess.getUserKey();
        // token路径，路径下保存登录信息
        String tokenPath = userKeyPath + ":" + authorityAccess.getToken();

        log.info("authorityAccess >>> {}", JSON.toJSONString(authorityAccess));
        redisUtil.set(tokenPath, JSON.toJSONString(authorityAccess), express);
    }

    @Override
    public AuthorityAccess getAuthorityAccessAndRefreshExpress(String token, Map<String, List<Long>> maps) {
        Object authorityAccessObject = redisUtil.get(ISMEDI_ACCESS_TOKEN + ":" + token);

        if (null == authorityAccessObject) {
            throw LogicException.raise(CustomError.TOKEN_NOT_AVAILABLE);
        }

        String authorityAccessString = authorityAccessObject.toString();
        AuthorityAccess authorityAccess = jsonHelper.jsonToObject(authorityAccessString, AuthorityAccess.class);
        if (null != maps) {
            authorityAccess.setDataScope(maps);
        }
        redisUtil.set(ISMEDI_ACCESS_TOKEN + ":" + token, jsonHelper.objectToJson(authorityAccess), TOKEN_TIME);

        return authorityAccess;
    }

    @Override
    public void deleteToken(String token) {
        redisUtil.del(ISMEDI_ACCESS_TOKEN + ":" + token);
    }

    @Override
    @SneakyThrows
    public void refreshDataScope(String path, Long express, AuthorityInfo authorityInfo, String device) {
        String token = authorityUtil.getAccessToken();
        Object authorityAccessObject = redisUtil.get(ISMEDI_ACCESS_TOKEN + ":" + token);

        if (null == authorityAccessObject) {
            throw LogicException.raise(CustomError.TOKEN_NOT_AVAILABLE);
        }

        String authorityAccessString = authorityAccessObject.toString();
        AuthorityAccess authorityAccess = jsonHelper.jsonToObject(authorityAccessString, AuthorityAccess.class);
        authorityAccess.setDataScope(authorityInfo.getDataScope());

        redisUtil.set(ISMEDI_ACCESS_TOKEN + ":" + token, jsonHelper.objectToJson(authorityAccess), TOKEN_TIME);
    }
}
